package com.bfxy.disruptor.common.balance;

import com.bfxy.disruptor.common.exception.AlertException;
import com.bfxy.disruptor.common.exception.TimeoutException;
import com.bfxy.disruptor.common.producer.Productor;
import com.bfxy.disruptor.common.waitStraty.WaitStrategy;

public final class ProcessingSequenceBarrier implements SequenceBarrier {
	private final WaitStrategy waitStrategy;// 等待策略
	private final Sequence dependentSequence;
	private volatile boolean alerted = false;
	private final Sequence cursorSequence;
	private final Productor sequencer;

	public ProcessingSequenceBarrier(final Productor sequencer, final WaitStrategy waitStrategy,
			final Sequence cursorSequence, final Sequence[] dependentSequences) {
		// 单或多生产者的ringBuffer控制器sequencer，这个只有一个，在ringbuuffer里面。
		//生产者没有栅栏，只有消费者才有栅栏，并且栅栏里面也有单或者多生产者sequencer。
		this.sequencer = sequencer;// 
		// 消费者等待可消费事件的策略
		this.waitStrategy = waitStrategy;
		//  
		this.cursorSequence = cursorSequence;//生产者对应的Sequence
		if (0 == dependentSequences.length) {//默认是空数组[]。
			//此时的dependentSequence就是生产者的sequence,即生产者一旦生产了数据，立马就可以进行消费。
			dependentSequence = cursorSequence;////与生产者相同的sequence。dependentSequence = cursorSequence = cursor
		} else {
			// 当依赖其他消费者时，dependentSequence就是其他消费者的序
			dependentSequence = new FixedSequenceGroup(dependentSequences);//被依赖的sequence,
		}
	}

	//消费者通过ProcessingSequenceBarrier的waitFor方法等待可消费序号，实际是调用WaitStrategy的waitFor方法。
	// 通过等待策略，协调生产者和消费者之间的平衡。
	@Override
	public long waitFor(final long sequence) throws AlertException, InterruptedException, TimeoutException {
		checkAlert();

		// 调用消费者去等待:sequence是下一个消费者想要的序号，cursorSequence是生产者序号（RingBuffer里面最大的序号值），
		// dependentSequence消费者序号，
		long availableSequence = waitStrategy.waitFor(sequence, cursorSequence, dependentSequence, this);

		if (availableSequence < sequence) {
			return availableSequence;
		}

		return sequencer.getHighestPublishedSequence(sequence, availableSequence);
	}

	@Override
	public long getCursor() {//获取当前能读取到的游标(cursor)值。
		return dependentSequence.get();
	}

	@Override
	public boolean isAlerted() {//barrier当前的状态是否是警报(alert)状态。
		return alerted;
	}

	@Override
	public void alert() {//提醒EventProcessor，一个状态发生了变化，直到清除之前，一直处于这种状态下。
		alerted = true;
		waitStrategy.signalAllWhenBlocking();
	}

	@Override
	public void clearAlert() {
		alerted = false;
	}

	@Override//检查是否提出了警报，如果提出了，就抛出异常。
	public void checkAlert() throws AlertException {
		if (alerted) {
			throw AlertException.INSTANCE;
		}
	}
}